var EasyMongo = require("../../common").EasyMongo;
var crawler = require('../../lib/crawler').Crawler;
var analyzer = require('../../lib/analyser').Analyzer;

var mapping = require("../../common").Mapping;
var di = require('../../common').DI;

var findCrawler = function (req, res, callback) {
    EasyMongo.find("crawler", {name: req.query.crawler}, function (err, docs) {
        if (err) res.send(mapping.errorCode.basicServerError);
        else {
            if (docs.length == 0) {
                res.send(mapping.errorCode.paramError);
            } else {
                // string to function
                if(docs[0].dataBuilder) {
                    var code = docs[0].dataBuilder.code;
                    code = code.substring(code.indexOf("{")+1, code.lastIndexOf("}")).trim();
                    docs[0].dataBuilder = new Function("cachedData", "cookieArray", "callback",code);
                }
                callback(docs[0], req, res);
            }
        }
    });
};

var buildRequestChain = function (crawlerConfig, req, res) {
    EasyMongo.find("request", {series: crawlerConfig.requestChain}, {}, function (err, docs) {
        if (err) res.send(mapping.errorCode.basicServerError);
        else {
            if (docs.length == 0) {
                res.send(mapping.errorCode.paramError);
            } else {
                // 1.sort by sequence
                docs.sort(function(a,b){return a.sequence> b.sequence?1:-1});

                // 2. build request chain
                var code = docs[0].filter.code;
                code = code.substring(code.indexOf("{")+1, code.lastIndexOf("}")).trim();
                docs[0].filter = new Function("err", "res", "body", "next", code);

                for (var i = 1; i < docs.length; i++) {
                    docs[i - 1].next = docs[i];
                    code = docs[i].filter.code;
                    code = code.substring(code.indexOf("{")+1, code.lastIndexOf("}")).trim();
                    docs[i].filter = new Function("err", "res", "body", "next", code);
                }
                crawlerConfig.requestChain = docs[0];
                // 3.inject analyzer
                addAnalyzer(req, res, crawlerConfig);
            }
        }
    });
};

var addAnalyzer = function (req, res, crawlerConfig) {
    EasyMongo.find("analyzer", {name: req.query.analyzer}, function (err, docs) {
        if (err) res.send(mapping.errorCode.basicServerError);
        else {
            if (docs.length == 0) {
                res.send(mapping.errorCode.paramError);
            } else {
                EasyMongo.find("executor", {name: docs[0].executorSeries}, function (err, functions) {
                    if (err) res.send(mapping.errorCode.basicServerError);
                    else {
                        // 4. build analyzer and executors
                        var exeArray = [];
                        var code = "";
                        functions.forEach(function (func) {
                            code = func.method.code;
                            code = code.substring(code.indexOf("{")+1, code.lastIndexOf("}")).trim();
                            exeArray.push({col: func.col, method: new Function("data","afterFilter", code),filter:func.filter});
                        });
                        docs[0].executorSeries = exeArray;

                        code = docs[0].method.code;
                        code = code.substring(code.indexOf("{")+1, code.lastIndexOf("}")).trim();
                        docs[0].method = new Function(code);
                        // 4.1 use di to inject dependencies
                        docs[0].scope = {};
                        docs[0].mode = true; // switch to mongodb mode
                        docs[0].mongo = EasyMongo; //register db api
                        di.generateScope(docs[0].scope,'analyzer');

                        // 5. start series process and inject di config
                        //try {
                            new analyzer(docs[0],function(al){
                                var cl = new crawler(crawlerConfig, al);
                                var scope = {};
                                di.generateScope(scope,'crawler');
                                cl.injectDependency(scope);
                                res.send(mapping.constString.startTurtleSuccess);
                            });
                        //} catch(e) {
                          //  res.send(e);
                        //}
                    }
                });
            }
        }
    });

};

exports.autoStartTurtle = function (req, res) {
    findCrawler(req, res, buildRequestChain);
};

exports.manualStart = function (req, res) {

};

exports.manualStop = function (req, res) {

};